package oss

import (
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"github.com/go-playground/validator/v10"
	"go.uber.org/zap"
)

// OSS 接入文档：https://help.aliyun.com/document_detail/32144.html

type Config struct {
	Endpoint         string     `json:"endpoint" validate:"required"`                  // 云存储域名
	AccessKeyId      string     `json:"access_key_id" validate:"required"`             // RAM 用户或 RAM 角色的 AccessKeyId
	AccessKeySecret  string     `json:"access_key_secret" validate:"required"`         // RAM 用户或 RAM 角色的 AccessKeySecret
	UseCname         bool       `json:"user_cname"`                                    // 是否将自定义域名绑定到存储空间上
	StsSecurityToken string     `json:"sts_security_token"`                            // 使用 STS 访问凭证
	ConnectTimeout   int64      `json:"connect_timeout"`                               // 客户端链接超时时间，默认 30s
	ReadWriteTimeout int64      `json:"read_write_timeout"`                            // 客户端读写超时时间，默认 60s
	Crc              string     `json:"crc" validate:"omitempty,oneof=enable disable"` // 上传、下载文件时是否开启（默认开启）CRC数据校验，确保上传、下载过程的数据完整性。
	Md5              string     `json:"md5" validate:"omitempty,oneof=enable disable"` // 是否开启（默认关闭） MD5 校验。推荐使用 CRC 校验，CRC 的效率高于MD5。
	Proxy            string     `json:"proxy"`                                         // 设置代理服务器地址
	AuthProxy        *AuthProxy `json:"auth_proxy" validate:"omitempty"`               // 设置携带账号密码的代理服务器
}

type AuthProxy struct {
	Host string `json:"host" validate:"required"`
	User string `json:"user" validate:"required"`
	Pwd  string `json:"pwd" validate:"required"`
}

type Handler struct {
	Client *oss.Client
	Logger *zap.Logger
}

func (c *Config) BuildClient() (client *oss.Client, err error) {
	// 配置校验
	if err = validator.New().Struct(c); err != nil {
		return nil, err
	}
	// 设置 Option
	opt := make([]oss.ClientOption, 0)
	if c.UseCname {
		opt = append(opt, oss.UseCname(c.UseCname))
	}
	if c.StsSecurityToken != "" {
		opt = append(opt, oss.SecurityToken(c.StsSecurityToken))
	}
	if c.ConnectTimeout != 0 && c.ReadWriteTimeout != 0 {
		opt = append(opt, oss.Timeout(c.ConnectTimeout, c.ReadWriteTimeout))
	}
	if c.Crc == "disable" {
		opt = append(opt, oss.EnableCRC(false))
	}
	if c.Md5 == "enable" {
		opt = append(opt, oss.EnableMD5(true))
	}
	if c.Proxy != "" {
		opt = append(opt, oss.Proxy(c.Proxy))
	}
	if c.AuthProxy != nil {
		opt = append(opt, oss.AuthProxy(c.AuthProxy.Host, c.AuthProxy.User, c.AuthProxy.Pwd))
	}
	// 构建 OSS 客户端
	return oss.New(c.Endpoint, c.AccessKeyId, c.AccessKeySecret, opt...)
}
